<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

/**
 * Class RequestCommand
 * @package App\Console\Commands
 */
class RequestCommand extends Command {
    use CommandTrait;
    /**
     * @var string
     */
    protected $signature = 'create:request {--table=}';
    /**
     * @var string
     */
    protected $basePath = "app/Requests";

    /**
     * @name: handle
     * @author: lisa
     * @datetime: 2021/8/3 14:07
     */
    public function handle() {
        $table = $this->option('table');
        if (!$table) $this->error('请输入表名');
        if (!$this->isTableExists($table)) $this->error("该表不存在");
        $structure = $this->getTableStructure($table);
        list($rules, $attrs, $primaryKey, $docs) = $this->getRulesAndAttrsAndPrimaryKey($table, $structure);
        $table = Str::singular($table);
        $this->storeRequestFile($table, $rules, $attrs, $docs);
        $this->deleteRequestFile($table, $rules, $attrs, $primaryKey);
    }

    /**
     * @param $table
     * @param $rules
     * @param $attrs
     * @param $docs
     * @name: storeRequestFile
     * @author: zhuxuesong
     * @datetime: 2022-01-12 16:36
     */
    public function storeRequestFile($table, $rules, $attrs, $docs) {
        $fileName = "{$table}/StoreRequest.php";
        $fileName = $this->getFileName($fileName);
        $path = $this->getPath($fileName);
        list($namespace, $className) = $this->getNamespaceAndClassName($path);
        $rules = $this->createPreArrayString($rules);
        $attrs = $this->createPreArrayString($attrs);
        $docs  = $this->createDocArrayToString($docs);
        $this->render($path, [
            'namespace' => $namespace,
            'className' => $className,
            'rules'     => $rules,
            'attrs'     => $attrs,
            'docs'      => $docs
        ],$this->getRenderHtml());
    }

    /**
     * @name: deleteRequestFile
     * @param $table
     * @param $rules
     * @param $attrs
     * @param $primaryKey
     * @author: lisa
     * @datetime: 2021/8/3 14:07
     */
    public function deleteRequestFile($table, $rules, $attrs, $primaryKey) {
        $fileName = "{$table}/DeleteRequest.php";
        $fileName = $this->getFileName($fileName);
        $path = $this->getPath($fileName);
        list($namespace, $className) = $this->getNamespaceAndClassName($path);
        $newRule = Arr::get($rules, $primaryKey);
        $newRule = str_replace('nullable', 'required', $newRule);
        $rules = [$primaryKey => $newRule];
        $rules = $this->createPreArrayString($rules);
        $newAttr = Arr::get($attrs, $primaryKey);
        $attrs = [$primaryKey => $newAttr];
        $attrs = $this->createPreArrayString($attrs);
        $this->render($path, [
            'namespace' => $namespace,
            'className' => $className,
            'rules'     => $rules,
            'attrs'     => $attrs
        ],$this->getRenderHtml());
    }

    /**
     * @name: getRulesAndAttrsAndPrimaryKey
     * @param $table
     * @param $tableStructure
     * @return array[]
     * @author: lisa
     * @datetime: 2021/8/3 13:53
     */
    public function getRulesAndAttrsAndPrimaryKey($table, $tableStructure) {
        $rules = [];
        $attrs = [];
        $docs  = [];
        $primaryKey = null;
        foreach ($tableStructure as $k => $v) {
            $field = Arr::get($v, 'Field');
            $key = Arr::get($v, 'Key');
            $type = Arr::get($v, 'Type');
            $null = Arr::get($v, 'Null');
            $label = Arr::get($v, 'Comment');
            $label = Str::before($label, '：');
            $tmpRules = [];
            if (in_array($field, ['is_delete', 'is_enable', 'created_at', 'updated_at', 'pass_word', 'token'])) continue;
            if ($this->isNotNull($null)) {
                if ($this->isPrimaryKey($key)) $tmpRules[] = 'nullable';
                else $tmpRules[] = 'required';
            } else {
                $tmpRules[] = 'nullable';
            }
            $docType = 'string';
            if ($this->isInteger($type)) {
                $tmpRules[] = 'integer|min:1';
                $docType = 'int';
            } else if ($this->isNumber($type)) {
                $tmpRules[] = 'numeric|min:0';
                $docType = 'float';
            } else if ($this->isString($type)) {
                $tmpRules[] = 'string';
                if ($this->isPhone($field)) $tmpRules[] = 'size:11|phone';
                else if ($this->isMobile($field)) $tmpRules[] = 'contact_tel';
                else if ($max = $this->getTypeMax($type)) $tmpRules[] = "max:{$max}";
            } else if ($this->isDateTime($type)) {
                $tmpRules[] = 'date_format:Y-m-d H:i:s';
            } else if ($this->isDate($type)) {
                $tmpRules[] = 'date_format:Y-m-d';
            } else if ($this->isTime($type)) {
                $tmpRules[] = 'date_format:H:i:s';
            }
            if ($this->isPrimaryKey($key)) {
                $tmpRules[] = "exists:{$table}";
                $label = '该数据';
                $primaryKey = $field;
            }
            $docs[] = '* @property ' . $docType . ' $' . $field . ' ' . $label;
            $rules[$field] = implode('|', $tmpRules);
            $attrs[$field] = $label;
        }
        return [$rules, $attrs, $primaryKey, $docs];
    }

    /**
     * @name: getRenderHtml
     * @return string
     * @author: lisa
     * @datetime: 2021/8/3 14:02
     */
    public function getRenderHtml()
    {
        return <<<html
<?php
namespace {namespace};
use App\Requests\BaseRequest;
/**
 {docs}
 */
class {className} extends BaseRequest
{
    /**
     * 定义规则信息
     *
     * @return array
     */
    public function rules()
    {
        return {rules};
    }
    /**
     * 定义字段对应的名称
     *
     * @return array
     */
    public function attributes()
    {
        return {attrs};
    }
}
html;
    }
}
